import pandas as pd
import numpy as np
import pickle
import dalex as dx
import warnings
warnings.filterwarnings('ignore')
Ze względu na restrykcje XGBoosta, który wymaga aby w nazwie zmiennych nie było znaków ">", "<" należy zmienić nazwę jednej kolummy.
df = pd.read_csv("housing_preprocessed.csv")
df = df.rename(columns={"<1H OCEAN": "1H OCEAN"})
X = df.drop("median_house_value", axis=1)
y = df[["median_house_value"]]
xgb = pickle.load(open("xgb.pickle", 'rb'))
df.head()
| longitude | latitude | housing_median_age | total_bedrooms | population | households | median_income | 1H OCEAN | INLAND | NEAR BAY | NEAR OCEAN | rooms_per_household | median_house_value | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 0.211155 | 0.567481 | 0.784314 | 0.019711 | 0.008941 | 0.020395 | 0.539668 | 0.0 | 0.0 | 1.0 | 0.0 | 0.046610 | 452600.0 |
| 1 | 0.212151 | 0.565356 | 0.392157 | 0.171349 | 0.067210 | 0.186842 | 0.538027 | 0.0 | 0.0 | 1.0 | 0.0 | 0.040945 | 358500.0 |
| 2 | 0.210159 | 0.564293 | 1.000000 | 0.029179 | 0.013818 | 0.028783 | 0.466028 | 0.0 | 0.0 | 1.0 | 0.0 | 0.056513 | 352100.0 |
| 3 | 0.209163 | 0.564293 | 1.000000 | 0.036163 | 0.015555 | 0.035691 | 0.354699 | 0.0 | 0.0 | 1.0 | 0.0 | 0.037750 | 341300.0 |
| 4 | 0.209163 | 0.564293 | 1.000000 | 0.043148 | 0.015752 | 0.042270 | 0.230776 | 0.0 | 0.0 | 1.0 | 0.0 | 0.041277 | 342200.0 |
observation = X.loc[[69]]
observation_target = y.loc[69][0]
Wyliczenie predykowanej przez model wartości.
observation_target_hat = xgb.predict(observation)[0]
observation_target_hat
119840.64
explainer = dx.Explainer(xgb, X, y)
Preparation of a new explainer is initiated -> data : 19643 rows 12 cols -> target variable : Parameter 'y' was a pandas.DataFrame. Converted to a numpy.ndarray. -> target variable : 19643 values -> model_class : xgboost.sklearn.XGBRegressor (default) -> label : Not specified, model's class short name will be used. (default) -> predict function : <function yhat_default at 0x000001E62D2D0AF0> will be used (default) -> predict function : Accepts only pandas.DataFrame, numpy.ndarray causes problems. -> predicted values : min = 2.73e+04, mean = 1.92e+05, max = 4.59e+05 -> model type : regression will be used (default) -> residual function : difference between y and yhat (default) -> residuals : min = -2.45e+05, mean = -1.54e+02, max = 3.06e+05 -> model_info : package xgboost A new explainer has been created!
ps = explainer.predict_surrogate(observation, type="lime")
ps.show_in_notebook()
observation0 = X.loc[[966]]
ps = explainer.predict_surrogate(observation0, type="lime")
ps.show_in_notebook()
observation1 = X.loc[[2000]]
ps = explainer.predict_surrogate(observation1, type="lime")
ps.show_in_notebook()
observation2 = X.loc[[2137]]
ps = explainer.predict_surrogate(observation2, type="lime")
ps.show_in_notebook()
observation3 = X.loc[[6900]]
ps = explainer.predict_surrogate(observation3, type="lime")
ps.show_in_notebook()
observation4 = X.loc[[12345]]
ps = explainer.predict_surrogate(observation4, type="lime")
ps.show_in_notebook()
Najbardziej istotne dla modelu są zmienne opisujące położenie nieruchomości oraz zarobki mieszkańców. W 4 z 6 powyższych obserwacji najistotniejszą zmienną jest median_income. \ \ Oprócz tego, widzimy, że dla wartości zmiennej median_income z tego samego przedziału (np. w observation2 i observation3 zmienna median_income jest w przedziale '<= 0.14') wpływ tej zmiennej na końcowy wynik predykcji jest niemalże identyczny dla obydwu tych obserwacji. Podobnie jest ze zmienną INLAND, w przypadku gdy jest równa 0, model podnosi przewidywaną cenę domu o ok. 57000, a gdy zmienna przyjmuje wartość 1 model opszucza przewidywaną cenę o ok. 56000.\ Zjawisko to jest obecne również w pozostałych zmiennych. \ \ Wobec tego, metoda LIME wydaję się być dość stabilna oraz poprawnie określać wpływ poszczególnych zmiennych na predykcję.